﻿using SocketTool.Com.Args;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SocketTool.Com.UDP.Client
{
    public class UDPClient : ISocket
    {
        private UdpClient mUdpClient = null;
        private Thread mRecvThread = null;
        private bool mRecving = true;

        private CustomerProtocol mProtocols;
        public DateTime LatestActiveTime { get; private set; }
        public IPEndPoint LocalEndPoint { get; }
        public IPEndPoint RemoteEndPoint { get; }

        public event EventHandler<ConnectionArgs> SocketConnectionChangedEvent;
        public event EventHandler<ReceiveMessageArgs> ReceiveMessageEvent;

        public UDPClient(string localIp, int localPort, string remoteIp, int remotePort)
        {
            this.LocalEndPoint = new IPEndPoint(IPAddress.Parse(localIp), localPort);
            this.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(remoteIp), remotePort);

            this.mUdpClient = new UdpClient(this.LocalEndPoint);
            this.mRecvThread = new Thread(ReceiveDataAsync);
            this.mRecvThread.IsBackground = true;
            this.mRecvThread.Start();
        }

        public void Close()
        {
            this.mRecving = false;
            this.mUdpClient.Close();
        }

        public bool Open()
        {
            return true;
        }

        public void Send(string msg, int count)
        {
            var msgBt = Encoding.UTF8.GetBytes(msg);
            var sendBt = this.mProtocols.GetSendData(msgBt);
            for (int i = 0; i < count; i++)
            {
                this.mUdpClient.Send(sendBt, sendBt.Length, this.RemoteEndPoint);
            }
        }

        public void SetCustomerProtocol(CustomerProtocol protocol)
        {
            this.mProtocols = protocol;
        }

        private async void ReceiveDataAsync()
        {
            while (this.mRecving)
            {
                var result = await mUdpClient.ReceiveAsync();
                this.LatestActiveTime = DateTime.Now;
                var bt = this.mProtocols.Parse(result.Buffer, out int readlen);
                string msg = Encoding.UTF8.GetString(bt);
                this.ReceiveMessageEvent?.Invoke(this, new Args.ReceiveMessageArgs(result.RemoteEndPoint, msg));
            }
        }
    }
}
